package com.penghe.www.baselibrary.adapter

import android.content.Context
import android.support.annotation.IdRes
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import java.lang.ref.WeakReference
import java.util.*

/**
 * Created by alm on 17-6-1.
 * 万能适配器
 */

abstract class AllPurposeAdapter<T> constructor(context: Context, dataList: ArrayList<T>, @IdRes itemLayoutId: Int) : BaseAdapter() {

    /**
     * 上下文弱引用
     */
    private val contextWeakReference: WeakReference<Context> = WeakReference(context)

    /**
     * 适配器数据源
     */
    private var mDataList: ArrayList<T> = dataList

    /**
     * 适配器item的布局id
     */
    @IdRes
    private val mItemLayoutId: Int = itemLayoutId

    /**
     * 自定义适配器总数(适配器会根据这个数与数据源的比例来显示)
     */
    private var mCountSum = -1

    //重写父类的函数

    /**
     * How many items are in the data set represented by this Adapter.

     * @return Count of items.
     */
    override fun getCount(): Int {
        if (mCountSum == -1) {
            return mDataList.size
        } else {
            return mCountSum
        }
    }

    /**
     * Get the data item associated with the specified position in the data set.

     * @param position Position of the item whose data we want within the adapter's
     * * data set.
     * *
     * @return The data at the specified position.
     */
    override fun getItem(position: Int): T {
        if (mCountSum == -1) {
            return mDataList[position]
        } else {
            return mDataList[mCountSum % mDataList.size]
        }
    }

    /**
     * Get the row id associated with the specified position in the list.

     * @param position The position of the item within the adapter's data set whose row id we want.
     * *
     * @return The id of the item at the specified position.
     */
    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    /**
     * Get a View that displays the data at the specified position in the data set. You can either
     * create a View manually or inflate it from an XML layout file. When the View is inflated, the
     * parent View (GridView, ListView...) will apply default layout parameters unless you use
     * [android.view.LayoutInflater.inflate]
     * to specify a root view and to prevent attachment to the root.

     * @param position The position of the item within the adapter's data set of the item whose view
     * *        we want.
     * *
     * @param convertView The old view to reuse, if possible. Note: You should check that this view
     * *        is non-null and of an appropriate type before using. If it is not possible to convert
     * *        this view to display the correct data, this method can create a new view.
     * *        Heterogeneous lists can specify their number of view types, so that this View is
     * *        always of the right type (see [.getViewTypeCount] and
     * *        [.getItemViewType]).
     * *
     * @param parent The parent that this view will eventually be attached to
     * *
     * @return A View corresponding to the data at the specified position.
     */
    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        val viewHolder: ViewHolder = getViewHolder(position, convertView, parent)
        convert(viewHolder, position, getItem(position))
        return viewHolder.getConvertView()
    }

    //自定义函数

    /**
     * 更新数据源并刷新适配器进行显示
     *
     * @param dataList 新的数据源
     */
    fun refresh(dataList: ArrayList<T>) {
        mDataList = dataList
        notifyDataSetChanged()
    }

    /**
     * 删除数据源中指定位置的数据
     *
     * @param position 指定删除位置
     */
    fun deleteListByPosition(position: Int) {
        if (position >= mDataList.size) {
            return
        }

        mDataList.removeAt(position)
        notifyDataSetChanged()
    }

    /**
     * 设置自定义数据总量
     *
     * @param countSum 自定义数据总量
     * @return AllPurposeAdapter本类对象
     */
    fun setCount(countSum: Int): AllPurposeAdapter<T> {
        mCountSum = countSum
        notifyDataSetChanged()
        return this
    }

    //内部私有函数

    /**
     * 获取VIewHolder
     *
     * @param position 当前位置
     * @param convertView
     */
    private fun getViewHolder(position: Int, convertView: View?, parent: ViewGroup?): ViewHolder {
        return ViewHolder.get(contextWeakReference.get()!!, convertView, parent, mItemLayoutId,
                position)
    }

    //抽象方法

    abstract fun convert(viewHolder: ViewHolder, position: Int, item: T)
}
